'''
    spider类
    断点调试（重要）
'''
import ssl # SSL证书相关
import re # 正则表达式
from urllib import request # python自带的模拟请求

class Spider():

    url = 'https://www.panda.tv/cate/lol' # 爬虫地址

    '''
    正则规则：
    [\s\S]：正则表达式匹配任意字符
    *：表示无限多次
    ?：非贪婪模式
    两端()表示组，这样可以去掉头尾的标签
    '''
    root_pattern = '<div class="video-info">([\s\S]*?)</div>' # 根节点的匹配模式
    name_pattern = '</i>([\s\S]*?)</span>' # 主播名字的匹配模式
    number_pattern = '<span class="video-number">([\s\S]*?)</span>' # 观看人数的匹配模式

    # 前面双下划线表示私有
    # 获取数据
    def __fetch_content(self):
        context = ssl._create_unverified_context() # 忽略https的ssl验证
        res = request.urlopen(Spider.url, context=context) # 模拟请求
        htmls = res.read() # 获取html
        htmls = str(htmls, encoding='utf-8') # 将htmls转成utf-8
        return htmls
    
    # 使用正则分析数据
    def __analysis(self, htmls):
        root_html = re.findall(Spider.root_pattern, htmls) # 找出所有根节点
        anchors_list = [] # 主播列表
        for html in root_html:
            name = re.findall(Spider.name_pattern, html) # 单个主播的名字
            number = re.findall(Spider.number_pattern, html) # 单个主播的人数
            # 生成主播相关的字典类型
            anchor = {
                'name': name,
                'number': number
            }
            anchors_list.append(anchor) # 把单个主播添加到主播列表
        return anchors_list

    # 精炼数据
    def __refine(self, anchors_list):
        # lambda 匿名函数
        l = lambda anchor: {
            'name': anchor['name'][0].strip(),
            'number': anchor['number'][0]
        }
        # map：把函数依次作用在列表上
        return map(l, anchors_list)

    # 列表排序
    def __sort(self, anchors_list):
        anchors_list = sorted(anchors_list, key=self.__sort_seed, reverse=True)
        return anchors_list

    # sorted 的 key 函数
    def __sort_seed(self, anchor):
        res = re.findall('\d*', anchor['number'])
        number = float(res[0])
        if '万' in anchor['number']:
            number *= 10000
        return number

    # 展示
    def __show(self, anchors_list):
        for rank in range(0, len(anchors_list)):
            print('rank ' + str(rank + 1) + ' : ' + anchors_list[rank]['name'] + '    ' + anchors_list[rank]['number'] + '人')

    # 入口方法
    def go(self):
        htmls = self.__fetch_content() # 调用私有方法
        anchors_list = self.__analysis(htmls)
        anchors_list_refine = list(self.__refine(anchors_list))
        anchors_list_sort = self.__sort(anchors_list_refine)
        self.__show(anchors_list_sort)

obj_spider = Spider()
obj_spider.go()
